import os
import time
import shutil
import unittest
import tempfile

#import buildbotweb
#os.environ['DJANGO_SETTINGS_MODULE'] = 'buildbotweb.settings'
#from testDB import enable_inmemory_testing_db
#enable_inmemory_testing_db('buildbotweb')

from testutils.mock import Mock

from autobbotd import buildbot
from autobbotd import buildtester

#import buildtester
DATALOC = os.path.dirname(buildtester.__file__)

from buildbotweb.buildbot.models import ( 
    Tests, TestRuns, UnitTestResults, TestSuites, TestSuiteRuns, TestStatuses, 
    TestSuiteTests, BTester, MailTestResults
)

from buildbotweb.buildbot import models

class Test_TestSuites(unittest.TestCase):
    def setUp(self):
        self.tmpdir = tempfile.mkdtemp()
        bt = BTester()
        bt.mailport = 25
        bt.newsport = 119
        bt.save()

        self.ts = TestSuites()
        self.ts.testsuite = "MyTest"
        self.ts.releasedir = self.tmpdir
        self.ts.testpath_id = 1
        self.ts.buildcmd = "echo %s %s %s; return 0"
        self.ts.btester = bt
        self.ts.save()

        for i in range(2):
            t = Tests()
            t.testname = "ATest_%s" % i
            t.testtype_id = 1
            t.testcmd = "echo 'TEST_%s! on %%s'" % i
            t.logpath = "%itest.log" % i
            t.errpath = "%itest.err" % i
            t.save()
            tst = TestSuiteTests()
            tst.testsuite_id = self.ts.id
            tst.test_id = t.id
            tst.save()

        self.origSvnPathInfo = models.getSvnPathInfo
        models.getSvnPathInfo = self._fakeSvnPathInfo
        self.orig_sendnews = BTester.sendnews
        BTester.sendnews = self._fakeSendnews
        self.orig_sendemail = BTester.sendemail
        BTester.sendemail = self._fakeSendemail


    def tearDown(self):
        shutil.rmtree(self.tmpdir)
        models.getSvnPathInfo = self.origSvnPathInfo
        BTester.sendnews = self.orig_sendnews
        BTester.sendemail = self.orig_sendemail

    def _fakeSvnPathInfo(self, svnpath):
        return "you", 1234, "Now"

    def _fakeSendnews(*args, **kwds):
        pass

    def _fakeSendemail(self, *args, **kwds):
        print args
        print kwds
        h = open(os.path.join(self.tmpdir, "mail.log"), 'w')
        try:
            h.write(args[2])
        finally:
            h.close()

    def testRun(self):
        """
        testRun

        Test the happy path
        """

        self.ts.run("testproj/test")

        results = os.listdir(self.tmpdir)
        results.sort()
        expectedResults = [
                'test_0test.err', 'test_0test.log', 'test_1test.err', 
                'test_1test.log', 'test_build.log', 'mail.log'
        ]
        expectedResults.sort()
        self.failUnlessEqual(results, expectedResults)

    def testFailRun(self):
        """
        testFailRun

        Test the case where the testsuite build fails.
        """
        pass

    def testErrorRun(self):
        """
        testErrorRun

        Test the case where the testsuite build errors out
        """
        self.ts.buildcmd = "echo 'Epic Fail!';"
        self.ts.run("testproj/test")

class Test_Tests(unittest.TestCase):
    def setUp(self):
        self.tmpdir = tempfile.mkdtemp()
        bt = BTester()
        bt.mailport = 25
        bt.newsport = 119
        bt.save()
        self.ts = TestSuites()
        self.ts.testsuite = "MyTest"
        self.ts.releasedir = self.tmpdir
        self.ts.testpath_id = 1
        self.ts.buildcmd = "echo %s %s %s"
        self.ts.btester = bt
        self.ts.save()
        self.tsr = TestSuiteRuns()
        self.tsr.testsuite = self.ts
        self.tsr.chrootdir = os.path.join(self.tmpdir, "FooTest")
        self.tsr.teststatus_id = 1
        self.tsr.svnrev = 1234
        self.tsr.testtime = time.strftime("%Y-%m-%d")
        self.tsr.save()
        self.t = Tests()
        self.t.testname = "FooTest"
        self.t.testcmd = "echo 'TEST on %s!'; return 0"
        self.t.logpath = "log.log"
        self.t.errpath = "err.err"
        self.t.testtype_id = 1
        self.t.save()
        self.orig_sendnews = BTester.sendnews
        BTester.sendnews = self._fakeSendnews
        self.orig_sendemail = BTester.sendemail
        BTester.sendemail = self._fakeSendemail

    def tearDown(self):
        shutil.rmtree(self.tmpdir)
        BTester.sendnews = self.orig_sendnews
        BTester.sendemail = self.orig_sendemail

    def _fakeSendnews(self, *args, **kwds):
        h = open(os.path.join(self.tmpdir, "failnews.log"), 'w')
        try:
            h.write(args[2])
        finally:
            h.close()

    def _fakeSendemail(self, *args, **kwds):
        h = open(os.path.join(self.tmpdir, "failmail.log"), 'w')
        try:
            h.write(args[1])
        finally:
            h.close()


    def testRun(self):
        """
        testRun

        Test the happy path where everything works correctly.
        """
        logpath = os.path.join(self.tmpdir, "FooTest")
        self.t.run(self.ts, self.tsr)

        h = open("%s_log.log" % logpath)
        try:
            data = h.read()
        finally:
            h.close()

        self.failUnlessEqual(data, "TEST on %s!\n" % logpath )

    def testErrorRun(self):
        """
        testErrorRun

        Test the case where the testcase errors out due to incorrect formatting.
        """
        self.t.testcmd = "echo 'Epic Fail!'; return 1"
        self.failUnlessRaises(
            TypeError,
            self.t.run,
            #(self.ts, os.path.join(self.tmpdir, "log.log"), 1234)
            (self.ts, self.tsr)
        )

    def testFailRun(self):
        """
        testFailRun

        Test the case where the testcase returns non-zero.
        """
        self.t.testcmd = "echo 'Epic Fail! on %s'; return 1"
        self.t.run(self.ts, self.tsr)

        logpath = os.path.join(self.tmpdir, "failnews.log")
        h = open(logpath)
        try:
            data = h.read()
        finally:
            h.close()

        self.failUnlessEqual(data, "[BUILDNTEST] FAIL! Test FooTest on FooTest Results 1234")

        logpath = os.path.join(self.tmpdir, "failmail.log")
        h = open(logpath)
        try:
            data = h.read()
        finally:
            h.close()

        self.failUnlessEqual(data, "[BUILDNTEST] Test FooTest on FooTest Failed at 1234")

class Test_TestRun(unittest.TestCase):
    def setUp(self):
        self.tmpdir = tempfile.mkdtemp()
        self.orig_sendemail = BTester.sendemail
        BTester.sendemail = self._fakeSendemail

    def tearDown(self):
        shutil.rmtree(self.tmpdir)
        BTester.sendemail = self.orig_sendemail

    def _fakeSendemail(self, *args, **kwds):
        h = open(os.path.join(self.tmpdir, "mail.log"), 'w')
        try:
            h.write(args[1])
        finally:
            h.close()

    def test_GetTestData_mtest(self):
        t = Tests()
        t.testname = "FooTest"
        t.testcmd = "echo %s; cat notafile; return 0"
        t.logpath = "log.log"
        t.errpath = "err.err"
        t.testtype_id = 1 
        t.save()
        
        ts = TestSuites()
        ts.testpath_id = 1
        ts.btester_id = 1
        ts.save()

        tsr = TestSuiteRuns()
        tsr.testsuite = ts
        tsr.teststatus_id = 1
        tsr.svnrev = 1234
        tsr.testtime = time.strftime("%Y-%m-%d")
        tsr.chrootdir = os.path.join(self.tmpdir, t.testname)
        tsr.save()
        
        os.makedirs(tsr.chrootdir)

        tr = TestRuns()
        tr.test = t
        tr.testsuiterun = tsr
        tr.testsuiterun_id = 1
        ret = tr.start()
        tr.stop(ret)
            
        resultpath = os.path.join(tsr.chrootdir, ".results")
        resultdata = [{
            'bytes_sec':100,
            'send_threads':1,
            'msgsize':2,
            'send_msgs_sec':1000,
            'recv_msgs_sec':900,
            'recv_latency':9.2,
        }]
        f = open(resultpath, 'w')
        try:
            f.write(str(resultdata))
        finally:
            f.close()

        tr.getTestData()

        files = os.listdir(tsr.chrootdir)
        self.failUnlessEqual(files, ['.results'])
       
        mtr = MailTestResults.objects.all()[0]
        self.failUnlessEqual(mtr.recv_bytes_sec, 100)
        self.failUnlessEqual(mtr.send_threads, 1)
        self.failUnlessEqual(mtr.recv_msgs_sec, 900)
        self.failUnlessEqual(mtr.send_msgs_sec, 1000)
        self.failUnlessEqual(mtr.recv_latency, 9)
        self.failUnlessEqual(mtr.msgsize, 2)
      
        self.failUnlessEqual(tr.logtail.strip(), tsr.chrootdir)
        self.failUnlessEqual(tr.errtail, 'cat: notafile: No such file or directory\n')

    def test_GetTestData_utest(self):
        t = Tests()
        t.testname = "FooTest"
        t.testcmd = "echo %s; cat notafile; return 0"
        t.logpath = "log.log"
        t.errpath = "err.err"
        t.testtype_id = 2 
        t.save()
        
        ts = TestSuites()
        ts.testpath_id = 1
        ts.btester_id = 1
        ts.save()

        tsr = TestSuiteRuns()
        tsr.testsuite = ts
        tsr.teststatus_id = 1
        tsr.svnrev = 1234
        tsr.testtime = time.strftime("%Y-%m-%d")
        tsr.chrootdir = os.path.join(self.tmpdir, t.testname)
        tsr.save()
        
        os.makedirs(tsr.chrootdir)

        tr = TestRuns()
        tr.test = t
        tr.testsuiterun = tsr
        tr.testsuiterun_id = 1
        ret = tr.start()
        tr.stop(ret)
            
        resultpath = os.path.join(tsr.chrootdir, ".results")
        resultdata = {
            'tests':10,
            'failures':1,
            'errors':2,
            'stmts':1001,
            'tested_stmts':900,
        }
        f = open(resultpath, 'w')
        try:
            f.write(str(resultdata))
        finally:
            f.close()

        tr.getTestData()

        files = os.listdir(tsr.chrootdir)
        self.failUnlessEqual(files, ['.results'])
      
        utr = tr.unittestresults_set.all()[0]
        print utr
        print dir(utr)

        self.failUnlessEqual(utr.numtests, 10)
        self.failUnlessEqual(utr.numfailures, 1)
        self.failUnlessEqual(utr.numerrors, 2)
      
        self.failUnlessEqual(tr.logtail.strip(), tsr.chrootdir)
        self.failUnlessEqual(tr.errtail, 'cat: notafile: No such file or directory\n')

    def test_GetTestData_Regression(self):
        # Setup test data
        t0 = Tests()
        t0.testname = "FooTest"
        t0.testcmd = "echo %s; cat '{\'one\':1}' > .results; return 0"
        t0.logpath = "log.log"
        t0.errpath = "err.err"
        t0.testtype_id = 2 
        t0.save()
        
        bt = BTester()
        bt.mailport = 25
        bt.newsport = 119
        bt.save()
        
        ts0 = TestSuites()
        ts0.testsuite = "TEST TEST"
        ts0.mailto = "foo@bar.com"
        ts0.testpath_id = 0
        ts0.btester = bt
        ts0.save()

        tsr0 = TestSuiteRuns()
        tsr0.testsuite = ts0
        tsr0.author = "Foo"
        tsr0.svnrev = "1234"
        tsr0.teststatus_id = 0
        tsr0.testtime = time.strftime("%Y-%m-%d")
        tsr0.chrootdir = self.tmpdir
        tsr0.save()

        tsr1 = TestSuiteRuns()
        tsr1.testsuite = ts0
        tsr1.author = "Bar"
        tsr1.svnrev = "1235"
        tsr1.teststatus_id = 0
        tsr1.testtime = time.strftime("%Y-%m-%d")
        tsr1.chrootdir = self.tmpdir
        tsr1.save()
    
        tr0 = TestRuns()
        tr0.test = t0 
        tr0.testsuiterun = tsr0
        tr0.testtime = time.strftime("%Y-%m-%d")
        tr0.teststatus_id = 0
        tr0.save()

        tr1 = TestRuns()
        tr1.test = t0
        tr1.testsuiterun = tsr1
        tr1.testtime = time.strftime("%Y-%m-%d")
        tr1.teststatus_id = 0
        tr1.save()

        utr0 = UnitTestResults()
        utr0.testrun = tr0
        utr0.numtests = 1000
        utr0.numfailures = 2
        utr0.numerrors = 1
        utr0.statements = 1000
        utr0.statements_executed = 900
        utr0.save()

        utr1 = UnitTestResults()
        utr1.testrun = tr1
        utr1.numtests = 999
        utr1.numfailures = 3
        utr1.numerrors = 2
        utr1.statements = 980
        utr1.statements_executed = 700
        utr1.save()
           
        resultpath = os.path.join(self.tmpdir, ".results")
        resultdata = {
            'tests':10,
            'failures':1,
            'errors':2,
            'stmts':1000,
            'tested_stmts':900,
        }
        f = open(resultpath, 'w')
        try:
            f.write(str(resultdata))
        finally:
            f.close()

        tr1.start()
        tr1.getTestData()

        h = open(os.path.join(self.tmpdir, 'mail.log'))
        try:
            data = h.read()
        finally:
            h.close()
        self.failUnlessEqual(
            "Code Regressions on %s at r1235" % os.path.basename(self.tmpdir),
            data
        )
   
        


class Test_BTester(unittest.TestCase):
    def setUp(self):
        self.tempdir = tempfile.mkdtemp()

    def tearDown(self):
        shutil.rmtree(self.tempdir)

    def _testSendNews(self):
        bt = BTester()
        bt.sendnews()

    def testSendEmail_BODYTEXT(self):
        bt = BTester()
        bt.messenger = Mock()
        bt.mailport = 25
        bt.newsport = 119
        bt.mailhost = "mail.na.nai.com"
        bt.save()
        bt.sendemail(
            'buildntest',
            'TEST',
            'matt_kubilus@mcafee.com',
            bodytext="TEST TEST TEST"
        )
        bt.messenger.mockCheckCall(
            0,
            'send_email',
            'mail.na.nai.com', 'matt_kubilus@mcafee.com', 'buildntest', 'TEST','TEST TEST TEST', []
        )

    def testSendEmail_BODYFILE(self):
        bt = BTester()
        bt.messenger = Mock()
        bt.mailport = 25
        bt.newsport = 119
        bt.mailhost = "mail.na.nai.com"
        bt.save()
        tfile = os.path.join(self.tempdir, "tfile")
        h = open(tfile, 'w')
        try:
            h.write("THIS is A TEST")
        finally:
            h.close()
        bt.sendemail(
            'buildntest',
            'TEST',
            'matt_kubilus@mcafee.com',
            bodyfile = tfile
        )
        bt.messenger.mockCheckCall(
            0,
            'send_email',
            'mail.na.nai.com', 'matt_kubilus@mcafee.com', 'buildntest', 'TEST', 'THIS is A TEST', []
        )

    def testSendEmail_ABODYFILE_TEXT(self):
        bt = BTester()
        bt.messenger = Mock()
        bt.mailport = 25
        bt.newsport = 119
        bt.mailhost = "mail.na.nai.com"
        bt.save()
        tfile = os.path.join(self.tempdir, "tfile")
        h = open(tfile, 'w')
        try:
            h.write("THIS is A TEST")
        finally:
            h.close()
        bt.sendemail(
            'buildntest',
            'TEST',
            'matt_kubilus@mcafee.com',
            bodytext = "FOO BAR BAZ",
            attachments = [tfile]
        )
        bt.messenger.mockCheckCall(
            0,
            'send_email',
            'mail.na.nai.com', 'matt_kubilus@mcafee.com', 'buildntest', 'TEST', 'FOO BAR BAZ', [tfile]
        )



class Test_Old(unittest.TestCase):
    def _testGetTestAllData(self):
        testdata_path = os.path.join(
            DATALOC,
            "testdata",
            "testalldata"
        )
        shutil.copy(
            testdata_path,
            os.path.join(self.tempdir, '.testalldata')
        )

        # Setup test data
        ts0 = TestSuites()
        ts0.testsuite = "TEST TEST"
        ts0.mailto = "foo@bar.com"
        ts0.testpath_id = 0
        ts0.save()

        status0 = TestStatuses()
        status0.teststatus = "s0"
        status1 = TestStatuses()
        status1.teststatus = "s1"
        status2 = TestStatuses()
        status2.teststatus = "s2"

        tsr0 = TestSuiteRuns()
        tsr0.testsuite = ts0
        tsr0.author = "Foo"
        tsr0.svnrev = "1234"
        tsr0.teststatus_id = 0
        tsr0.testtime = time.strftime("%Y-%m-%d")
        tsr0.save()

        tsr1 = TestSuiteRuns()
        tsr1.testsuite = ts0
        tsr1.author = "Bar"
        tsr1.svnrev = "1235"
        tsr1.teststatus_id = 0
        tsr1.testtime = time.strftime("%Y-%m-%d")
        tsr1.save()
    
        tr0 = TestRuns()
        tr0.test_id = 2
        tr0.testsuiterun = tsr0
        tr0.testtime = time.strftime("%Y-%m-%d")
        tr0.teststatus_id = 0
        tr0.save()

        tr1 = TestRuns()
        tr1.test_id = 2
        tr1.testsuiterun = tsr1
        tr1.testtime = time.strftime("%Y-%m-%d")
        tr1.teststatus_id = 0
        tr1.save()

        utr0 = UnitTestResults()
        utr0.testrun = tr0
        utr0.numtests = 1000
        utr0.numfailures = 2
        utr0.numerrors = 1
        utr0.statements = 1000
        utr0.statements_executed = 900
        utr0.save()

        utr1 = UnitTestResults()
        utr1.testrun = tr1
        utr1.numtests = 999
        utr1.numfailures = 3
        utr1.numerrors = 2
        utr1.statements = 980
        utr1.statements_executed = 700
        utr1.save()

        bt = buildbot.BuildTester(
            "testuser"            
        )
        bt.getTestAllData(
            self.tempdir,
            tr1.id,
            #"matt_kubilus@mcafee.com"
            "foo@bar.com"
        )


if __name__ == "__main__":
    unittest.main()
